package jwtsso

import (
	"errors"
	"net/http"
	"strings"
	"time"

	"github.com/dgrijalva/jwt-go"
)

type JwtSsoSdk struct {
	SecretKey []byte
	Issuer    string
	Audience  string
}

func NewJwtSsoSdk(secretKey, issuer, audience string) *JwtSsoSdk {
	return &JwtSsoSdk{
		SecretKey: []byte(secretKey),
		Issuer:    issuer,
		Audience:  audience,
	}
}

func (j *JwtSsoSdk) GenerateToken(userId int64, roleId int, name string) (string, error) {
	claims := jwt.MapClaims{
		"iss":     j.Issuer,
		"aud":     j.Audience,
		"exp":     time.Now().Add(time.Hour * 1).Unix(),
		"iat":     time.Now().Unix(),
		"user_id": userId,
		"role_id": roleId,
		"name":    name,
	}

	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
	return token.SignedString(j.SecretKey)
}

func (j *JwtSsoSdk) ValidateToken(tokenString string) (map[string]interface{}, error) {
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		return j.SecretKey, nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		if claims["iss"] != j.Issuer || claims["aud"] != j.Audience {
			return nil, errors.New("invalid issuer or audience")
		}
		return map[string]interface{}{
			"user_id": claims["user_id"],
			"role_id": claims["role_id"],
			"name":    claims["name"],
		}, nil
	}

	return nil, errors.New("invalid token")
}

func (j *JwtSsoSdk) GetTokenFromHeader(r *http.Request) string {
	bearerToken := r.Header.Get("Authorization")
	if len(strings.Split(bearerToken, " ")) == 2 {
		return strings.Split(bearerToken, " ")[1]
	}
	return ""
}
